package cn.stylefeng.guns.modular.gridsystem.activemq;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.stylefeng.guns.modular.gridsystem.config.ActiveMqConf;
import cn.stylefeng.guns.modular.gridsystem.constants.ExceptionConstant;
import cn.stylefeng.guns.modular.gridsystem.constants.FaultModelConstant;
import cn.stylefeng.guns.modular.gridsystem.constants.UploadQueueLogConstant;
import cn.stylefeng.guns.modular.gridsystem.entity.*;
import cn.stylefeng.guns.modular.gridsystem.event.FaultLogEvent;
import cn.stylefeng.guns.modular.gridsystem.event.param.FaultLog;
import cn.stylefeng.guns.modular.gridsystem.model.param.*;
import cn.stylefeng.guns.modular.gridsystem.mqtt.MqttTopicConstant;
import cn.stylefeng.guns.modular.gridsystem.mqtt.MyMqttClient;
import cn.stylefeng.guns.modular.gridsystem.mqtt.result.FaultWarning;
import cn.stylefeng.guns.modular.gridsystem.service.*;
import cn.stylefeng.guns.modular.gridsystem.utils.EngineUtil;
import cn.stylefeng.guns.modular.gridsystem.utils.MyConst;
import cn.stylefeng.guns.modular.gridsystem.utils.MyFileUtils;
import cn.stylefeng.guns.modular.gridsystem.utils.WavTransformUtil;
import io.netty.handler.codec.mqtt.MqttProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQObjectMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jms.*;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.*;

import static cn.stylefeng.guns.modular.gridsystem.utils.WavTransformUtil.read;

/**
 * @author ssy
 * @date 2021/11/3 9:22
 */
@Component
@Slf4j
public class ActiveMqConsumer {

    @Value("${third-push-event.enable}")
    private Boolean pushEventEnable;

    @Resource
    private ActiveMqProduceService activeMqProduceService;

    @Resource
    private BizGatewayChannelService bizGatewayChannelService;

    @Resource
    private BizGatewayService bizGatewayService;

    @Resource
    private BizExceptionService bizExceptionService;

    @Resource
    private BizExceptionLogService exceptionLogService;

    @Resource
    private BizStationService stationService;

    @Resource
    private BizUploadQueueLogService uploadQueueLogService;

    @Resource
    private BizFaultModelService faultModelService;

    @Resource
    private ThirdPartyInterconnectionService thirdPartyInterconnectionService;

    @Resource
    private BizDeviceService deviceService;

    @Resource
    private BizIndustryInvolvedService industryInvolvedService;

    @Resource
    private BizThreholdItemService threholdItemService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private MyMqttClient myMqttClient;

   // @Resource
   // private MqttProperties mqttProperties;

    // 1:N
    @JmsListener(destination = ActiveMqConf.myQueue, containerFactory = "jmsListenerContainerFactory")
    public void receive(ActiveMQObjectMessage mqMessage, Session session) throws Exception {

        //更新待验证队列状态
        BizUploadQueueLogParam bizUploadQueueLog = (BizUploadQueueLogParam) mqMessage.getObject();
        bizUploadQueueLog.setStatus(UploadQueueLogConstant.STATUS_PROCESSING);
        uploadQueueLogService.edit(bizUploadQueueLog);

        //获取音频文件
        String path = MyFileUtils.getUploadPath() + "/" + bizUploadQueueLog.getFilePath();
       // log.info("获取音频文件 >>>>>>>>>>>>>>>>>>>>>>" + path);

        //判断是不是16k 采样率（不是就转成16k）
        File f = new File(path);
        try (RandomAccessFile rdf = new RandomAccessFile(f, "r")) {
            int frequency = WavTransformUtil.toInt(read(rdf, 24, 4));
            if (frequency != 16000) {
                String[] split = path.split("\\.");
                String copyPath = split[0] + "(to16k)." + split[1];
                File file = new File(copyPath);
                boolean newFile = file.createNewFile();
                if (newFile) {
                    boolean transWav = WavTransformUtil.transWav(f, file, 16000);
                    if (transWav) {
                        path = copyPath;
                    }
                }
            }
        }

        //查询是否有第三方
        final Integer gatewayId = bizUploadQueueLog.getGatewayId();
        final BizGateway bizGateway = bizGatewayService.getById(gatewayId);
        if (ObjectUtil.isNull(bizGateway)) {
            throw new RuntimeException(MyConst.GATEWAY_NOT_EXIST);
        }
        final String gatewayCode = bizGateway.getGatewayCode();
        //电站Id
        final Integer stationId = bizGateway.getStationId();
        //查询电站
        final BizStation station = stationService.getById(stationId);
        if (ObjectUtil.isNull(station)) {
            throw new RuntimeException(MyConst.STATION_NOT_EXIST);
        }
        //获取通道信息
        final BizGatewayChannel bizGatewayChannel = bizGatewayChannelService.listByGatewayId(bizUploadQueueLog.getGatewayId(), bizUploadQueueLog.getGatewayChannel());
        final Integer deviceId = bizGatewayChannel.getDeviceId();
        final BizDevice device = deviceService.getById(deviceId);
        if (ObjectUtil.isNull(device)) {
            throw new RuntimeException(MyConst.DEVICE_NOT_EXIST);
        }
        final Integer industryId = device.getIndustryId();
        BizIndustryInvolved bizIndustryInvolved = industryInvolvedService.getById(industryId);

        if (ObjectUtil.isNull(bizIndustryInvolved)) {
            throw new RuntimeException(MyConst.INDUSTRY_NOT_EXIST);
        }
        final Integer groupId = bizIndustryInvolved.getGroupId();

        int errorType = ExceptionConstant.ERROR_TYPE_UNKNOWN;
        //1:n
        String recognize = "";
        try {
            recognize = EngineUtil.recognize(path, String.valueOf(groupId));
        } catch (Exception e) {
            log.warn(" 调用引擎异常啦 EngineUtil.recognize>>>> {}", recognize);
            return;
        }
        JSONObject jsonObject = JSONUtil.parseObj(recognize);
        String code = jsonObject.get("code").toString();
        log.info("1:N结果：" + recognize);

        if (code.equals("200")) {

            Object data = jsonObject.get("data");
            JSONObject jsonObject1 = JSONUtil.parseObj(data);
            Set<String> strings = jsonObject1.keySet();
            Iterator<String> iterator = strings.iterator();
            //获取1：N的故障模型
            String key = iterator.next();
            String score = jsonObject1.get(key).toString();

            BizThreholdItemParam bizThreholdItemParam = new BizThreholdItemParam();
            bizThreholdItemParam.setGatewayId(gatewayId);
            bizThreholdItemParam.setGatewayChannel(bizGatewayChannel.getChannel());
            BizThreholdItem bizThreholdItem = threholdItemService.threholdItemByChannelAndGatewayId(bizThreholdItemParam);
            double threholdItem = 60.0;
            if (ObjectUtil.isNotNull(bizThreholdItem)) {
                threholdItem = Double.parseDouble(bizThreholdItem.getThresholdValue());
            }
            log.info("阈值：{}", threholdItem);
            //根据算法模型id查询模型数据
            BizFaultModel bizFaultModel = faultModelService.getOneByAccessToken(key);
            String errorName = MyConst.UNKNOWN_FAULT;
            String faultNumber = MyConst.UNKNOWN_FAULT_NUMBER;
            if (ObjectUtil.isNotNull(bizFaultModel) && Double.parseDouble(score) > threholdItem) {
                String faultLevel = bizFaultModel.getFaultLevel();
                faultNumber = bizFaultModel.getAccessToken();
                //如果故障等级为正常的故障等级，则删除故障文件，忽略其他操作
                if (FaultModelConstant.FAULT_LEVEL_NORMAL.equals(faultLevel)) {
                    //删除文件
                    boolean isDelete = FileUtil.del(f);
                    log.info("删除文件结果：{},文件路径：{}", isDelete ? "成功" : "失败", path);
                    return;
                }
                errorName = bizFaultModel.getFaultName();
            }
            log.info("故障名称：{}", errorName);

            //查询当天是否存在对应网关、设备的故障信息
            BizExceptionParam bizExceptionParam = new BizExceptionParam();
            bizExceptionParam.setDeviceId(deviceId);
            bizExceptionParam.setErrorName(errorName);
            bizExceptionParam.setGatewayCode(gatewayCode);
            bizExceptionParam.setAccessToken(key);
            bizExceptionParam.setCreatedAt(DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt()));
            BizException bizException = bizExceptionService.listByErrorNameAndToday(bizExceptionParam);
            Integer bizExceptionId;
            String createTimeWhitError;
            if (!MyConst.UNKNOWN_FAULT.equals(errorName)) {
                errorType = ExceptionConstant.ERROR_TYPE_KNOWN;
            }
            if (ObjectUtil.isNotNull(bizException) && errorName.equals(bizException.getErrorName()) && gatewayCode.equals(bizException.getGatewayCode()) && deviceId.equals(bizException.getDeviceId())) {
                // true 当天有数据
                //故障与最新一条故障相同
                createTimeWhitError = DateUtil.formatDateTime(bizException.getCreatedAt());
                bizExceptionId = bizException.getId();
            } else {
                // true 当天无数据
                //设置为1:1时间
                createTimeWhitError = DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt());
                BizExceptionParam bizExceptionInsertParam = new BizExceptionParam();
                String gatewayChannel = bizUploadQueueLog.getGatewayChannel();
                if (ObjectUtil.isNotNull(gatewayChannel)) {
                    bizExceptionInsertParam.setDeviceId(deviceId);
                }
                bizExceptionInsertParam.setErrorName(errorName);
                bizExceptionInsertParam.setCreatedAt(createTimeWhitError);

                bizExceptionInsertParam.setErrorType(errorType);
                bizExceptionInsertParam.setGatewayCode(gatewayCode);
                bizExceptionInsertParam.setStatus(0);
                bizExceptionInsertParam.setAccessToken(bizUploadQueueLog.getAccessToken());
                bizExceptionId = bizExceptionService.addAndReturnId(bizExceptionInsertParam);
                if (bizExceptionId == 0) {
                    throw new RuntimeException(MyConst.INSERT_EXCEPTION_ERROR);
                }
                log.info("新添加故障：{}", bizExceptionInsertParam);
            }

            BizExceptionLogParam bizExceptionLogparam = new BizExceptionLogParam();
            bizExceptionLogparam.setExceptionId(bizExceptionId);
            bizExceptionLogparam.setCreatedAt(createTimeWhitError);
            bizExceptionLogparam.setFileName(bizUploadQueueLog.getFilePath());
            bizExceptionLogparam.setGatewayChannel(bizUploadQueueLog.getGatewayChannel());
            bizExceptionLogparam.setGatewayCode(bizUploadQueueLog.getGatewayCode());
            bizExceptionLogparam.setAccessToken(key);
            bizExceptionLogparam.setVoiceScore(bizUploadQueueLog.getScore());
            //设置为1:1时间
            bizExceptionLogparam.setExceptionTime(bizUploadQueueLog.getCreatedAt());
            exceptionLogService.add(bizExceptionLogparam);
            log.info("添加子故障：{}", bizExceptionLogparam);
            bizUploadQueueLog.setStatus(UploadQueueLogConstant.STATUS_PROCESSED);
            uploadQueueLogService.edit(bizUploadQueueLog);

            //第三方事件
            if (pushEventEnable) {
                FaultLog faultLog = new FaultLog();
                faultLog.setGatewayCode(gatewayCode);
                faultLog.setChannel(bizUploadQueueLog.getGatewayChannel());
                faultLog.setFaultCategory(bizExceptionParam.getErrorName());
                faultLog.setFaultType(bizException.getErrorType());
                faultLog.setAccessToken(bizUploadQueueLog.getAccessToken());
                faultLog.setFaultTime(DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt()));
                faultLog.setStatus(bizExceptionParam.getStatus());
                faultLog.setFilePath(path);
                applicationEventPublisher.publishEvent(new FaultLogEvent(faultLog));
            }

            //mqtt推送
          //  if (mqttProperties.isEnable()) {
            if (false) {
                FaultWarning faultWarning = new FaultWarning();
                faultWarning.setStationName(station.getStationName());
                faultWarning.setWarnName(errorName);
                faultWarning.setStationAddress(station.getStationAddress());
                faultWarning.setGatewayCode(gatewayCode);
                faultWarning.setGatewayChannel(bizGatewayChannel.getChannel());
                faultWarning.setDeviceId(device.getId());
                faultWarning.setDeviceName(device.getDeviceName());
                faultWarning.setVoiceUrl(bizUploadQueueLog.getFilePath());
                faultWarning.setInstallLocation(bizGatewayChannel.getInstallLocation());
                faultWarning.setDateTime(DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt()));
                faultWarning.setScore(score);
                faultWarning.setErrorType(errorType);
                if (errorType == ExceptionConstant.ERROR_TYPE_UNKNOWN) {
                    faultWarning.setAccessToken(ExceptionConstant.UNKNOWN_FAULT_ACCESSTOKEN);
                } else {
                    faultWarning.setAccessToken(key);
                }
                myMqttClient.publish(MqttTopicConstant.ALARM_PUSH, JSONUtil.toJsonStr(faultWarning));
            }

            //获取第三方列表
            Long orgId = station.getOrgId();
            ThirdPartyInterconnectionParam interconnectionParam = new ThirdPartyInterconnectionParam();
            interconnectionParam.setOrgId(orgId);
            List<ThirdPartyInterconnection> list = thirdPartyInterconnectionService.list(interconnectionParam);

        /*    ThirdIntegerfaceParam integerfaceParam = new ThirdIntegerfaceParam();
            integerfaceParam.setStationName(station.getStationName());
            integerfaceParam.setGatewayCode(bizExceptionLogparam.getGatewayCode());
            integerfaceParam.setGatewayChannel(bizExceptionLogparam.getGatewayChannel());
            integerfaceParam.setStationAddress(station.getStationAddress());
            integerfaceParam.setWarnName(errorName);
            integerfaceParam.setVoiceUrl(bizExceptionLogparam.getFileName());
            integerfaceParam.setDateTime(bizExceptionLogparam.getExceptionTime().toString());
            integerfaceParam.setScore(score);
          //  integerfaceParam.setFaultNumber(faultNumber);
            integerfaceParam.setList(list);*/
            ThirdIntegerfaceParam integerfaceParam = new ThirdIntegerfaceParam();
            integerfaceParam.setStationName(station.getStationName());
            integerfaceParam.setGatewayCode(bizExceptionLogparam.getGatewayCode());
            integerfaceParam.setGatewayChannel(bizExceptionLogparam.getGatewayChannel());
            integerfaceParam.setStationAddress(station.getStationAddress());
            integerfaceParam.setWarnName(errorName);
            log.info("****写入到消息队列的文件路径是：" + path);
            integerfaceParam.setVoiceUrl(path);
            integerfaceParam.setDateTime(bizExceptionLogparam.getExceptionTime().toString());
            integerfaceParam.setScore(score);
            integerfaceParam.setGatewayName(bizGateway.getGatewayName());
            integerfaceParam.setDeviceId(deviceId);   //(device.getId());
            integerfaceParam.setInstallLocation(bizGatewayChannel.getInstallLocation());
            integerfaceParam.setErrorType(errorType);
            integerfaceParam.setList(list);

            String deviceName = "";
            if (ObjectUtil.isNotEmpty(device.getDeviceName())) {
                deviceName = device.getDeviceName();
            }

            integerfaceParam.setDeviceName(deviceName);

            if (!list.isEmpty()) {
                activeMqProduceService.sendThirdParty(integerfaceParam);
                log.info("加入到第三方推送队列");
            }
            log.info("消费成功===>{}", bizUploadQueueLog.getId());
            mqMessage.acknowledge();
        } else {
            log.info("1:N失败===>{}", bizUploadQueueLog.getId());
            String error = jsonObject.get("error").toString();
            if ("The group id does not exist".equals(error)) {
                Integer bizExceptionId;
                String createTimeWhitError;
                String errorName = "初始未知故障";
                //生成故障日志
                BizExceptionParam bizExceptionParam = new BizExceptionParam();
                bizExceptionParam.setDeviceId(deviceId);
                bizExceptionParam.setErrorName(errorName);
                bizExceptionParam.setGatewayCode(gatewayCode);
                bizExceptionParam.setAccessToken(ExceptionConstant.UNKNOWN_FAULT_ACCESSTOKEN);
                bizExceptionParam.setCreatedAt(DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt()));
                BizException bizException = bizExceptionService.listByErrorNameAndToday(bizExceptionParam);
                if (ObjectUtil.isNotNull(bizException) && errorName.equals(bizException.getErrorName()) && gatewayCode.equals(bizException.getGatewayCode()) && deviceId.equals(bizException.getDeviceId())) {
                    // true 当天有数据
                    //故障与最新一条故障相同
                    createTimeWhitError = DateUtil.formatDateTime(bizException.getCreatedAt());
                    bizExceptionId = bizException.getId();
                } else {
                    // true 当天无数据
                    //设置为1:1时间
                    createTimeWhitError = DateUtil.formatDateTime(bizUploadQueueLog.getCreatedAt());
                    BizExceptionParam bizExceptionInsertParam = new BizExceptionParam();
                    String gatewayChannel = bizUploadQueueLog.getGatewayChannel();
                    if (ObjectUtil.isNotNull(gatewayChannel)) {
                        bizExceptionInsertParam.setDeviceId(deviceId);
                    }
                    bizExceptionInsertParam.setErrorName(errorName);
                    bizExceptionInsertParam.setCreatedAt(createTimeWhitError);
                    bizExceptionInsertParam.setErrorType(ExceptionConstant.ERROR_TYPE_UNKNOWN);
                    bizExceptionInsertParam.setGatewayCode(gatewayCode);
                    bizExceptionInsertParam.setStatus(0);
                    bizExceptionInsertParam.setAccessToken(bizUploadQueueLog.getAccessToken());
                    bizExceptionId = bizExceptionService.addAndReturnId(bizExceptionInsertParam);
                    if (bizExceptionId == 0) {
                        throw new RuntimeException(MyConst.INSERT_EXCEPTION_ERROR);
                    }
                }

                BizExceptionLogParam bizExceptionLogparam = new BizExceptionLogParam();
                bizExceptionLogparam.setExceptionId(bizExceptionId);
                bizExceptionLogparam.setCreatedAt(createTimeWhitError);
                bizExceptionLogparam.setFileName(bizUploadQueueLog.getFilePath());
                bizExceptionLogparam.setGatewayChannel(bizUploadQueueLog.getGatewayChannel());
                bizExceptionLogparam.setGatewayCode(bizUploadQueueLog.getGatewayCode());
                bizExceptionLogparam.setAccessToken(ExceptionConstant.UNKNOWN_FAULT_ACCESSTOKEN);
                bizExceptionLogparam.setVoiceScore(bizUploadQueueLog.getScore());
                //设置为1:1时间
                bizExceptionLogparam.setExceptionTime(bizUploadQueueLog.getCreatedAt());
                exceptionLogService.add(bizExceptionLogparam);
                bizUploadQueueLog.setStatus(UploadQueueLogConstant.STATUS_PROCESSED);
                uploadQueueLogService.edit(bizUploadQueueLog);
                log.info("消费成功===>无模型未知故障");
                mqMessage.acknowledge();
            } else {
                session.recover();
                throw new RuntimeException("引擎调用异常");
            }
        }

}

    /**
     * 推送到第三方
     *
     * @param mqMessage
     * @param session
     * @throws JMSException
     */
    @JmsListener(destination = ActiveMqConf.thirdQueue, containerFactory = "jmsListenerContainerFactory")
    public void thirdReceive(ActiveMQObjectMessage mqMessage, Session session) throws JMSException {
        ThirdIntegerfaceParam thirdIntegerfaceParam = (ThirdIntegerfaceParam) mqMessage.getObject();
        List<ThirdPartyInterconnection> list = thirdIntegerfaceParam.getList();
        Map<String, Object> param = new HashMap<>();
   /*     param.put("stationName", thirdIntegerfaceParam.getStationName());
        param.put("dateTime", thirdIntegerfaceParam.getDateTime());
        param.put("voiceUrl", thirdIntegerfaceParam.getVoiceUrl());
        param.put("warnName", thirdIntegerfaceParam.getWarnName());
        param.put("stationAddress", thirdIntegerfaceParam.getStationAddress());
        param.put("gatewayCode", thirdIntegerfaceParam.getGatewayCode());
        param.put("gatewayChannel", thirdIntegerfaceParam.getGatewayChannel());
        param.put("deviceName", thirdIntegerfaceParam.getDeviceName());
        param.put("score", thirdIntegerfaceParam.getScore());
        param.put("faultNumber", thirdIntegerfaceParam.getFaultNumber());*/
        param.put("stationName", thirdIntegerfaceParam.getStationName());
        param.put("dateTime", thirdIntegerfaceParam.getDateTime());
        String filePath = MyFileUtils.getUploadPath() + "/" + thirdIntegerfaceParam.getVoiceUrl();
        //  log.info("*********拿到的文件地址是：" + filePath);

        param.put("warnFile", new File(filePath));
        param.put("voiceUrl", thirdIntegerfaceParam.getVoiceUrl());
        param.put("warnName", thirdIntegerfaceParam.getWarnName());
        param.put("stationAddress", thirdIntegerfaceParam.getStationAddress());
        param.put("gatewayCode", thirdIntegerfaceParam.getGatewayCode());
        param.put("gatewayChannel", thirdIntegerfaceParam.getGatewayChannel());
        param.put("deviceName", thirdIntegerfaceParam.getDeviceName());
        param.put("score", thirdIntegerfaceParam.getScore());
        param.put("deviceId", thirdIntegerfaceParam.getDeviceId());
        param.put("installLocation", thirdIntegerfaceParam.getInstallLocation());
        param.put("errorType", thirdIntegerfaceParam.getErrorType());
        //
        String gatewayName = bizGatewayService.lambdaQuery().eq(BizGateway::getGatewayCode, thirdIntegerfaceParam.getGatewayCode()).one().getGatewayName();
        param.put("gatewayName", gatewayName);

        log.info("thirdReceive() 告警参数>>>******************" + param);
        // log.info("gatewayName >>>******************" + gatewayName);

        for (ThirdPartyInterconnection thirdPartyInterconnection : list) {
            String thirdPartyUrl = thirdPartyInterconnection.getThirdPartyUrl();
            if (ObjectUtil.isNotEmpty(thirdPartyUrl)) {
                try {
//                    String post = HttpRequest.post(thirdPartyUrl).body(JSONUtil.toJsonStr(param)).execute().body();
                    String post = HttpUtil.post(thirdPartyUrl, param, 20000);
//                    final JSONObject parseObj = JSONUtil.parseObj(post);
//                    int code1 = parseObj.getInt("code");
//                    if (code1 != 200) {
//                        session.rollback();
//                        log.error("第三方Http调用失败==>500{}",thirdPartyUrl);
//                        throw new RuntimeException("第三方Http调用异常");
//                    }
                    //  log.warn("返回的告警参数如下 ===>{}", JSONUtil.toJsonStr(param));
                    //   log.info("第三方返回===>{}", post);
                    log.info("第三方消费成功===>{}", thirdPartyUrl);
                    mqMessage.acknowledge();
                } catch (Exception e) {
                    session.recover();
                    log.error("第三方Http调用异常===>{}", thirdPartyUrl);
                    throw new RuntimeException("第三方Http调用异常");
                }
            } else {
                log.error("第三方HttpUrl不存在==>{}", thirdPartyUrl);
                mqMessage.acknowledge();
            }
        }
    }

}
